class Compiler{
    constructor(vm){
        console.log(vm)
        this.el=vm.$el
        this.vm=vm
        this.compile(this.el)
    }
    compile(el){
        //编译模板 处理文本节点和元素节点
        let childNodes=el.childNodes
        Array.from(childNodes).forEach(node=>{
            if(this.isTextNode(node)){
                this.compielText(node)
            }else if(this.isElementNode(node)){
                this.compileElement(node)
            }
            // console.log(node.childNodes.length)
            //判断node节点是否有子节点。如果有子节点 就要递归调用compile
            if(node.childNodes && node.childNodes.length){
                this.compile(node)
            }
        })
    }
    compileElement(node){
        // 处理元素节点、处理指令
        // console.log(node.attributes)
        Array.from(node.attributes).forEach(attr=>{
            //判断是否是指令
            let attrName=attr.name
            if(this.isDirective(attr.name)){
                // node.textContent=this.vm[attr.nodeValue]
                // node.value=this.vm[attr.nodeValue]
                attrName=attrName.substr(2)
                let key=attr.value
                this.update(node,key,attrName)
            }
        })
    }

    update(node,key,attrName){
        console.log(this)
        let updatefn=this[attrName+'Updater']
        updatefn&&updatefn.call(this,node,this.vm[key],key)
    }
    textUpdater(node,value,key){
        node.textContent=value
        new Watcher(this.vm,key,(newValue)=>{
            node.textContent=newValue
        })
    }
    modelUpdater(node,value,key){
        node.value=value
        new Watcher(this.vm,key,(newValue)=>{
            node.value=newValue
        })
        
        node.addEventListener('input',()=>{
            this.vm[key]=node.value
        })
    }
    compielText(node){
        // 编译文本节点，处理插值表达式
        // console.dir(node)
        // {{msg}}
        let reg=/\{\{(.+?)\}\}/
        let value=node.textContent
        if(reg.test(value)){
            let key=RegExp.$1.trim();
            node.textContent=value.replace(reg,this.vm[key])

            // 创建Watcher对象当数据改变更新视图
            new Watcher(this.vm,key,(newValue)=>{
                node.textContent=newValue
            })
        }
    }
    
    isDirective(attrName){
        //判断元素属性是否是指令
        return attrName.startsWith('v-')  //判断元素是否为v- 开头
    }
    isTextNode(node){
        // 判断节点是否是文本节点
        return node.nodeType===3
    }

    isElementNode(node){
        // 判断节点是否是元素节点
        return node.nodeType===1
    }
}